package com.qbm.association.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qbm.association.bean.UserTypeEnum;
import com.qbm.association.entity.Student;
import com.qbm.association.mapper.StudentMapper;
import com.qbm.association.service.AdministratorService;
import com.qbm.association.service.PasswordService;
import com.qbm.association.service.StudentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.lang.Assert;

import lombok.extern.log4j.Log4j;
import org.apache.poi.sl.usermodel.Sheet;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Aron
 * @since 2022-02-07
 */


@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    @Resource
    private StudentMapper studentMapper;

    @Resource
    private PasswordService passwordService;


    @Override
    public Student getByUsername(String username) {
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name",username);
        Student student  = studentMapper.selectOne(queryWrapper);
        return student;
    }

    @Override
    @Transactional
    public void register(Student student, String password) {
        boolean isTrue = studentMapper.insert(student)==1;
        Assert.isTrue(isTrue,"注册失败");
        isTrue = passwordService.insertUserPassword(student.getId(), UserTypeEnum.STUDENT,password);
        Assert.isTrue(isTrue,"注册失败");

    }

    @Override
    public void writeExcel(String path) {
        // 注意 simpleWrite在数据量不大的情况下可以使用（5000以内，具体也要看实际情况），数据量大参照 重复多次写入
        List<Student> students = studentMapper.selectList(new QueryWrapper<>());
        // 这里 需要指定写用哪个class去写
        ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcel.write(path, Student.class).build();
            WriteSheet writeSheet = EasyExcel.writerSheet("学生信息").build();
            excelWriter.write(students, writeSheet);
        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void excelImport(MultipartFile file) {
        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(file.getInputStream());
            EasyExcelFactory.read(bufferedInputStream, null, new AnalysisEventListener<Object>() {
                List<Object> list = new ArrayList();
                @Override
                public void invoke(Object data, AnalysisContext context) {
                    System.err.println(data.toString());
                    //可以在此实现业务代码
                    list.add(data);
                    // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
                    if (list.size() >= 100) {
                        saveData();
                        // 存储完成清理 list
                        list.clear();
                    }
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    // 这里也要保存数据，确保最后遗留的数据也存储到数据库
                    saveData();
                }

                /**
                 * 加上存储数据库
                 */
                private void saveData() {
                    for(Object temp : list) {
                        Student student = new Student();
                        Map map = JSONObject.parseObject(JSONObject.toJSONString(temp), Map.class);

                        student.setStudentId(Integer.parseInt(map.get(0).toString()));
                        student.setName(map.get(1).toString());
                        student.setUserName(map.get(2).toString());
                        student.setSex(map.get(3).toString());
                        student.setAssociation(map.get(4).toString());
                        student.setGrade(map.get(5).toString());
                        register(student,student.getStudentId().toString());
                    }
                }
            }).sheet().doRead();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
